<?php 
class DomArManyToManyTestCase extends DomArTestUnitTestCase {
	
	public function testConstruct() {
		$a = new DomArManyToManyTestClass('a');
		$c = new DomArManyToManyChildTestClass('c');
		
		$prop = $a->getProperty('children');
		$this->assertIdentical( $prop->childClassName, 'DomArManyToManyChildTestClass');
		$this->assertIdentical( $prop->className, 'DomArManyToManyTestClass' );
		$this->assertIdentical( $prop->inverse, 'parents' );
		$this->assertIdentical( $prop->actAsParent, true );
		$this->assertIdentical( $prop->composition, true );
		
		$prop = $c->getProperty('parents');
		$this->assertIdentical( $prop->childClassName, 'DomArManyToManyTestClass');
		$this->assertIdentical( $prop->className, 'DomArManyToManyChildTestClass' );
		$this->assertIdentical( $prop->inverse, 'children' );
		$this->assertIdentical( $prop->actAsParent, false );
		$this->assertIdentical( $prop->composition, false );
		
		
		
		$prop = $a->getProperty('aggrChildren');
		$this->assertIdentical( $prop->childClassName, 'DomArManyToManyChildTestClass');
		$this->assertIdentical( $prop->className, 'DomArManyToManyTestClass' );
		$this->assertIdentical( $prop->inverse, 'aggrParents' );
		$this->assertIdentical( $prop->actAsParent, true );
		$this->assertIdentical( $prop->composition, false );
		
		$prop = $c->getProperty('aggrParents');
		$this->assertIdentical( $prop->childClassName, 'DomArManyToManyTestClass');
		$this->assertIdentical( $prop->className, 'DomArManyToManyChildTestClass' );
		$this->assertIdentical( $prop->inverse, 'aggrChildren' );
		$this->assertIdentical( $prop->actAsParent, false );
		$this->assertIdentical( $prop->composition, false );
		
		
		
		$prop = $a->getProperty('parents');
		$this->assertIdentical( $prop->childClassName, 'DomArManyToManyChildTestClass');
		$this->assertIdentical( $prop->className, 'DomArManyToManyTestClass' );
		$this->assertIdentical( $prop->inverse, 'children' );
		$this->assertIdentical( $prop->actAsParent, false );
		$this->assertIdentical( $prop->composition, false );
		
		$prop = $c->getProperty('children');
		$this->assertIdentical( $prop->childClassName, 'DomArManyToManyTestClass');
		$this->assertIdentical( $prop->className, 'DomArManyToManyChildTestClass' );
		$this->assertIdentical( $prop->inverse, 'parents' );
		$this->assertIdentical( $prop->actAsParent, true );
		$this->assertIdentical( $prop->composition, false );
		
	}
	
	public function testBasics() {
		
		DomArManyToManyTestClass::getTable()->update();
		
		$a1 = new DomArManyToManyTestClass('a1');
		$a2 = new DomArManyToManyTestClass('a2');
		
		$b = new DomArManyToManyChildTestClass('b');
		$c = new DomArManyToManyChildTestClass('c');

		$a1->children[] = $b;
		$a1->children[] = $c;
		
		$a2->children[] = $b;
		$a2->children[] = $c;
		
		$a1->save();

		
		DomAr::flushStoredObjects();
		
		$aa1 = DomArManyToManyTestClass::load($a1->id);
		
		// test children
		$children = $aa1->children->query()->commit()->toArray();
		$this->assertEqual( count($children), 2);
		$this->assertIdentical( $children[0]->id, $b->id );
		$this->assertIdentical( $children[1]->id, $c->id );
		$bb = $children[0];
		
		// test child parents
		$children = $bb->parents->query()->commit()->toArray();
		$this->assertEqual( count($children), 2);
		$this->assertIdentical( $children[0]->id, $a1->id );
		$this->assertIdentical( $children[1]->id, $a2->id );
		
		
		// delete a1
		$aa1->delete();
		
		
		// test that aa1 deleted all children
		$aa2 = DomArManyToManyTestClass::load($a2->id);
		$children = $aa2->children->query()->commit()->toArray();
		$this->assertEqual( count($children), 0);
	
		// delete a2
		$aa2->delete();

		$this->assertTableEmpty( $a1->getTableName() );
		$this->assertTableEmpty( $b->getTableName() );

	}
	
	public function testRemove() {
		
		DomArManyToManyTestClass::getTable()->update();
		
		$a1 = new DomArManyToManyTestClass('a1');
		
		$b = new DomArManyToManyChildTestClass('b');
		$c = new DomArManyToManyChildTestClass('c');

		$a1->children[] = $b;
		$a1->children[] = $c;
		$this->assertEqual( count($a1->children->getNewObjects()), 2);

		$a1->children->remove( $b );
		$this->assertEqual( count($a1->children->getNewObjects()), 1);
		$this->assertIdentical( count($b->parents->getNewObjects()), 0 );

		$a1->children[] = $b;

		$a1->save();
		
		$this->assertEqual( $a1->children->count(), 2);
		
		$a1->children->remove( $b );
		$this->assertIdentical( $b->parents->count(), 0 );
		$this->assertEqual( $a1->children->count(), 1);
	}
	
	public function testDelete() {
		
		DomArManyToManyTestClass::getTable()->update();
		
		$a1 = new DomArManyToManyTestClass('a1');
		
		$b = new DomArManyToManyChildTestClass('b');
		$c = new DomArManyToManyChildTestClass('c');

		$a1->children[] = $b;
		$a1->children[] = $c;
		$this->assertEqual( count($a1->children->getNewObjects()), 2);

		$a1->save();
		
		$this->assertEqual( $a1->children->count(), 2);
		$this->assertIdentical( $b->parents->count(), 1 );
		$this->assertEqual( $c->parents->count(), 1);
		
		$b->delete();
		$this->assertEqual( $a1->children->count(), 1);
		$this->assertIdentical( $b->parents->count(), 0 );
		$this->assertEqual( $c->parents->count(), 1);
		
		$a1->delete();
		$this->assertEqual( $a1->children->count(), 0);
		$this->assertIdentical( $b->parents->count(), 0 );
		$this->assertEqual( $c->parents->count(), 0);
		
	}
	
	public function testSaveParent() {
		
		DomArManyToManyTestClass::getTable()->update();
		
		$a1 = new DomArManyToManyTestClass('a1');
		
		$b = new DomArManyToManyChildTestClass('b');
		$c = new DomArManyToManyChildTestClass('c');

		$a1->children[] = $b;
		$a1->children[] = $c;

		$b->save();
	
	}
	
	public function testItemValidator() {
		
		$item = new DomArManyToManyVChild();
		$item->text = 'notMain';
		$ch = new DomArManyToManyVChild();
		$ch->text = 'good';

		
		
		$item->items[] = $ch;
		$this->assertFalse( $item->validated() );
		$this->assertEqual( $item->getValidationMessages(), array('I Only main is allowed, notMain was given') );

		$item->setValidated(true);
		$ch->setValidated(true);
		$ch->parents[] = $item;
		$this->assertFalse( $ch->validated() );
		$this->assertEqual( $ch->getValidationMessages(), array('P Only main is allowed, notMain was given') );
		
		
		
		$item->setValidated(true);	
		$ch->setValidated(true);
		$item->text = 'main';
		$ch->text = 'bad';
		$item->items[] = $ch;
		$this->assertFalse( $item->validated() );
		$this->assertEqual( $item->getValidationMessages(), array('I My error bad') );

		$item->setValidated(true);
		$ch->setValidated(true);
		$ch->parents[] = $item;
		$this->assertFalse( $ch->validated() );
		$this->assertEqual( $ch->getValidationMessages(), array('P My error bad') );
		
		
		
		$item->setValidated(true);
		$ch->setValidated(true);	
		$item->text = 'main';
		$ch->text = 'good';
		$item->items[] = $ch;
		$this->assertTrue( $item->validated() );	}

	public function testReAdding() {
		DomArManyToManyListener::getTable()->update();
		
		$a = new DomArManyToManyListener();
		$b = new DomArManyToManyListener();
		
		// reset A
		$a->reset();
		$b->reset();
		$this->assertIdentical( $a->beforeAddChildCount, 0 );
		$this->assertIdentical( $a->afterAddChildCount, 0 );
		$this->assertIdentical( $b->beforeAddParentCount, 0 );
		$this->assertIdentical( $b->afterAddParentCount, 0 );
		
		// -------------------------------
		// ADD ITEM (unsaved)
		$a->items[] = $b;
		$this->assertIdentical( $a->beforeAddChildCount, 1 );
		$this->assertIdentical( $a->afterAddChildCount, 1 );
		$this->assertIdentical( $b->beforeAddParentCount, 1 );
		$this->assertIdentical( $b->afterAddParentCount, 1 );	
		
		// -------------------------------
		// SAVE AND RELOAD
		$a->save();
		$a->items[] = $b;
		$this->assertIdentical( $a->beforeAddChildCount, 1 );
		$this->assertIdentical( $a->afterAddChildCount, 1 );
		$this->assertIdentical( $b->beforeAddParentCount, 1 );
		$this->assertIdentical( $b->afterAddParentCount, 1 );
		
		DomAr::flushStoredObjects();
		$a = DomArManyToManyListener::load( $a->id );
		$b = DomArManyToManyListener::load( $b->id );
		$a->reset();
		$b->reset();
		
		// -------------------------------
		// ADD ITEM AGAIN (saved)

		$a->items[] = $b;
		$this->assertIdentical( $a->beforeAddChildCount, 0 );
		$this->assertIdentical( $a->afterAddChildCount, 0 );
		$this->assertIdentical( $b->beforeAddParentCount, 0 );
		$this->assertIdentical( $b->afterAddParentCount, 0 );
		
		// -------------------------------
		// TEST parent saved and child not
		$a = new DomArManyToManyListener();
		$b = new DomArManyToManyListener();
		$a->save();
		
		// ADD ITEM
		$a->items[] = $b;
		$this->assertIdentical( $a->beforeAddChildCount, 1 );
		$this->assertIdentical( $a->afterAddChildCount, 1 );
		$this->assertIdentical( $b->beforeAddParentCount, 1 );
		$this->assertIdentical( $b->afterAddParentCount, 1 );
		
		// ADD AGAIN
		$a->items[] = $b;
		$this->assertIdentical( $a->beforeAddChildCount, 1 );
		$this->assertIdentical( $a->afterAddChildCount, 1 );
		$this->assertIdentical( $b->beforeAddParentCount, 1 );
		$this->assertIdentical( $b->afterAddParentCount, 1 );
		
		
	}
	
	public function testListeners() {
		DomArManyToManyListener::getTable()->update();
		
		$a = new DomArManyToManyListener();
		$b = new DomArManyToManyListener();
		$c = new DomArManyToManyListener();
		$d = new DomArManyToManyListener();
		$e = new DomArManyToManyListener();
		
		// reset A
		$a->reset();
		$b->reset();
		$c->reset();
		$d->reset();
		$e->reset();
		
		
		$this->assertIdentical( $a->setValidatorChild, 1 );
		$this->assertIdentical( $a->beforeAddChild, 1 );
		$this->assertIdentical( $a->afterAddChild, 1 );
		$this->assertIdentical( $a->beforeRemoveChild, 1 );
		$this->assertIdentical( $a->afterRemoveChild, 1 );
		
		$this->assertIdentical( $a->setValidatorParent, 1 );
		$this->assertIdentical( $a->beforeAddParent, 1 );
		$this->assertIdentical( $a->afterAddParent, 1 );
		$this->assertIdentical( $a->beforeRemoveParent, 1 );
		$this->assertIdentical( $a->afterRemoveParent, 1 );
		
		$this->assertIdentical( $a->setValidatorChildCount, 0 );
		$this->assertIdentical( $a->beforeAddChildCount, 0 );
		$this->assertIdentical( $a->afterAddChildCount, 0 );
		$this->assertIdentical( $a->beforeRemoveChildCount, 0 );
		$this->assertIdentical( $a->afterRemoveChildCount, 0 );
		
		$this->assertIdentical( $a->setValidatorParentCount, 0 );
		$this->assertIdentical( $a->beforeAddParentCount, 0 );
		$this->assertIdentical( $a->afterAddParentCount, 0 );
		$this->assertIdentical( $a->beforeRemoveParentCount, 0 );
		$this->assertIdentical( $a->afterRemoveParentCount, 0 );
		
		
		// -------------------------------
		// ADD ITEM (unsaved)
		// -------------------------------
		$a->items[] = $b;
		$this->assertIdentical( $a->setValidatorChild, 0 );
		$this->assertIdentical( $a->beforeAddChild, 0 );
		$this->assertIdentical( $a->afterAddChild, 0 );

		$this->assertIdentical( $b->setValidatorParent, 0 );
		$this->assertIdentical( $b->beforeAddParent, 0 );
		$this->assertIdentical( $b->afterAddParent, 0 );
		
		$this->assertIdentical( $a->setValidatorChildCount, 1 );
		$this->assertIdentical( $a->beforeAddChildCount, 1 );
		$this->assertIdentical( $a->afterAddChildCount, 1 );
		$this->assertIdentical( $a->beforeRemoveChildCount, 0 );
		$this->assertIdentical( $a->afterRemoveChildCount, 0 );
		$this->assertIdentical( $a->setValidatorParentCount, 0 );
		$this->assertIdentical( $a->beforeAddParentCount, 0 );
		$this->assertIdentical( $a->afterAddParentCount, 0 );
		$this->assertIdentical( $a->beforeRemoveParentCount, 0 );
		$this->assertIdentical( $a->afterRemoveParentCount, 0 );
		
		$this->assertIdentical( $b->setValidatorChildCount, 0 );
		$this->assertIdentical( $b->beforeAddChildCount, 0 );
		$this->assertIdentical( $b->afterAddChildCount, 0 );
		$this->assertIdentical( $b->beforeRemoveChildCount, 0 );
		$this->assertIdentical( $b->afterRemoveChildCount, 0 );
		$this->assertIdentical( $b->setValidatorParentCount, 1 );
		$this->assertIdentical( $b->beforeAddParentCount, 1 );
		$this->assertIdentical( $b->afterAddParentCount, 1 );
		$this->assertIdentical( $b->beforeRemoveParentCount, 0 );
		$this->assertIdentical( $b->afterRemoveParentCount, 0 );
		
		
		// -------------------------------
		// REMOVE ITEM (unsaved)
		// -------------------------------
		$a->reset();
		$b->reset();
		$a->items->remove( $b );
		
		$this->assertIdentical( $a->beforeRemoveChild, 0 );
		$this->assertIdentical( $a->afterRemoveChild, 0 );
		
		$this->assertIdentical( $b->beforeRemoveParent, 0 );
		$this->assertIdentical( $b->afterRemoveParent, 0 );
		
		$this->assertIdentical( $a->setValidatorChildCount, 0 );
		$this->assertIdentical( $a->beforeAddChildCount, 0 );
		$this->assertIdentical( $a->afterAddChildCount, 0 );
		$this->assertIdentical( $a->beforeRemoveChildCount, 1 );
		$this->assertIdentical( $a->afterRemoveChildCount, 1 );
		$this->assertIdentical( $a->setValidatorParentCount, 0 );
		$this->assertIdentical( $a->beforeAddParentCount, 0 );
		$this->assertIdentical( $a->afterAddParentCount, 0 );
		$this->assertIdentical( $a->beforeRemoveParentCount, 0 );
		$this->assertIdentical( $a->afterRemoveParentCount, 0 );
		
		$this->assertIdentical( $b->setValidatorChildCount, 0 );
		$this->assertIdentical( $b->beforeAddChildCount, 0 );
		$this->assertIdentical( $b->afterAddChildCount, 0 );
		$this->assertIdentical( $b->beforeRemoveChildCount, 0 );
		$this->assertIdentical( $b->afterRemoveChildCount, 0 );
		$this->assertIdentical( $b->setValidatorParentCount, 0 );
		$this->assertIdentical( $b->beforeAddParentCount, 0 );
		$this->assertIdentical( $b->afterAddParentCount, 0 );
		$this->assertIdentical( $b->beforeRemoveParentCount, 1 );
		$this->assertIdentical( $b->afterRemoveParentCount, 1 );
		

		
		// -------------------------------
		// ADD ITEM (saved)
		// -------------------------------
		$a->reset();
		$a->save();
		$d->save();
		$a->items[] = $d;
		
		$this->assertIdentical( $a->setValidatorChild, 0 );
		$this->assertIdentical( $a->beforeAddChild, 0 );
		$this->assertIdentical( $a->afterAddChild, 0 );

		$this->assertIdentical( $d->setValidatorParent, 0 );
		$this->assertIdentical( $d->beforeAddParent, 0 );
		$this->assertIdentical( $d->afterAddParent, 0 );
		
		$this->assertIdentical( $a->setValidatorChildCount, 1 );
		$this->assertIdentical( $a->beforeAddChildCount, 1 );
		$this->assertIdentical( $a->afterAddChildCount, 1 );
		$this->assertIdentical( $a->beforeRemoveChildCount, 0 );
		$this->assertIdentical( $a->afterRemoveChildCount, 0 );
		$this->assertIdentical( $a->setValidatorParentCount, 0 );
		$this->assertIdentical( $a->beforeAddParentCount, 0 );
		$this->assertIdentical( $a->afterAddParentCount, 0 );
		$this->assertIdentical( $a->beforeRemoveParentCount, 0 );
		$this->assertIdentical( $a->afterRemoveParentCount, 0 );
		
		$this->assertIdentical( $d->setValidatorChildCount, 0 );
		$this->assertIdentical( $d->beforeAddChildCount, 0 );
		$this->assertIdentical( $d->afterAddChildCount, 0 );
		$this->assertIdentical( $d->beforeRemoveChildCount, 0 );
		$this->assertIdentical( $d->afterRemoveChildCount, 0 );
		$this->assertIdentical( $d->setValidatorParentCount, 1 );
		$this->assertIdentical( $d->beforeAddParentCount, 1 );
		$this->assertIdentical( $d->afterAddParentCount, 1 );
		$this->assertIdentical( $d->beforeRemoveParentCount, 0 );
		$this->assertIdentical( $d->afterRemoveParentCount, 0 );
		
		// -------------------------------
		// REMOVE ITEM (saved) (child side)
		// -------------------------------
		$a->reset();
		$d->reset();
		$a->items->remove( $d );
		
		$this->assertIdentical( $a->beforeRemoveChild, 0 );
		$this->assertIdentical( $a->afterRemoveChild, 0 );
		
		$this->assertIdentical( $d->beforeRemoveParent, 0 );
		$this->assertIdentical( $d->afterRemoveParent, 0 );
		
		$this->assertIdentical( $a->setValidatorChildCount, 0 );
		$this->assertIdentical( $a->beforeAddChildCount, 0 );
		$this->assertIdentical( $a->afterAddChildCount, 0 );
		$this->assertIdentical( $a->beforeRemoveChildCount, 1 );
		$this->assertIdentical( $a->afterRemoveChildCount, 1 );
		$this->assertIdentical( $a->setValidatorParentCount, 0 );
		$this->assertIdentical( $a->beforeAddParentCount, 0 );
		$this->assertIdentical( $a->afterAddParentCount, 0 );
		$this->assertIdentical( $a->beforeRemoveParentCount, 0 );
		$this->assertIdentical( $a->afterRemoveParentCount, 0 );
		
		$this->assertIdentical( $d->setValidatorChildCount, 0 );
		$this->assertIdentical( $d->beforeAddChildCount, 0 );
		$this->assertIdentical( $d->afterAddChildCount, 0 );
		$this->assertIdentical( $d->beforeRemoveChildCount, 0 );
		$this->assertIdentical( $d->afterRemoveChildCount, 0 );
		$this->assertIdentical( $d->setValidatorParentCount, 0 );
		$this->assertIdentical( $d->beforeAddParentCount, 0 );
		$this->assertIdentical( $d->afterAddParentCount, 0 );
		$this->assertIdentical( $d->beforeRemoveParentCount, 1 );
		$this->assertIdentical( $d->afterRemoveParentCount, 1 );
		
		
	}

} 
?>